﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Motoball.screenmanager;
using Motoball.Paddles;

namespace Motoball
{
    public class Ball
    {
/*
*	Circle Ball
*	code by Marcus Pflanz
*	graphics by Jonas Daehnert
*	copyright _tapetegaming 2008-2009
*/
        //indicates which player hit the ball last
        /// <summary>
        /// false == player1 hit ball last
        /// true == player2 hit ball last
        /// </summary>
        bool playerFlag = true;
        
        Vector3 color;
        GameScreen screen;

        public bool active = true;

        public Vector3 spin = Vector3.Zero;
        float rotation = 0;
        ModelBone[] rings;
        Matrix[] ringMatrices;

        public DiffBloomModel model;
        Vector3 direction;
        Vector3 position;
        float speed = 0.0f;
        float initSpeed = 2300f;
        float acceleration = 100.0f;

        public Ball(Color color, GameScreen screen)
        {
            this.screen = screen;
            direction = new Vector3(0.0f);
            position = Vector3.Zero;
            Speed = initSpeed;
            rings = new ModelBone[3];
            ringMatrices = new Matrix[3];
        }
        
        #region Properties
        public Vector3 Direction
        {
            get { return direction; }
            set { direction = value; }
        }

        //indicates which player hit ball last
        public bool PlayerFlag
        {
            get { return playerFlag; }
            set { playerFlag = value; }
        }

        public Vector3 Position
        {
            get { return position; }
            set { position = value; }
        }

        public float Speed
        {
            get { return speed; }
            set { speed = value; }
        }
        public Vector3 Color
        {
            get { return color; }
            set { color = value;
            model.diffColors["Ball_Zentrum"] = color;
            }
        }

        private Camera Camera
        {
            get { return GameScreen.Camera; }
        }
        #endregion

        #region Methods
       
        public void LoadContent(ContentManager content)
        {
            model = new DiffBloomModel(content.Load<Model>("Models\\Ball"));
           

            rings[0] = model.model.Bones["Ball_Ring"];
            ringMatrices[0] = rings[0].Transform;
            rings[1] = model.model.Bones["Ball_Ring1"];
            ringMatrices[1] = rings[1].Transform;
            rings[2] = model.model.Bones["Ball_Ring2"];
            ringMatrices[2] = rings[2].Transform;

            model.diffColors["Ball_Ring"] = new Vector3(0f);
            model.diffColors["Ball_Ring1"] = new Vector3(0f);
            model.diffColors["Ball_Ring2"] = new Vector3(0f);

            
        }

        public void Reset(float targetRotation)
        {
            Direction = new Vector3(0.0f, 0.0f, 1.0f);
            model.bloomingMeshes["Ball_Zentrum"] = "default";
            Direction = RotateY(Direction, targetRotation);
            spin = Vector3.Zero;
            position = Vector3.Zero;
            model.World = Matrix.CreateTranslation(position);
            color = Vector3.One;
            Speed = initSpeed;
        }
        float bla = 0;
        public void Reflect(Paddle hitPlayer)
        {
            Speed += acceleration;
            GameplayScreen.screenManager.Input.RumblePad(hitPlayer.PlayerIndex, 0.5f, 0.5f);
            Vector3 normal = Vector3.TransformNormal(Vector3.UnitY, hitPlayer.World);
            Vector3 between = Vector3.Lerp(normal, -direction, 0.5f);
            direction = Vector3.Reflect(direction, between);
            direction.Y = 0;
            direction.Normalize();
            bla = hitPlayer.delta;
            //Vector3 spinAdd = new Vector3(-normal.Y, 0f, normal.X) * hitPlayer.delta/4f ;
            
            
            //debug-info
            //reflection = direction;
            //reflector = normal;
            PlayerFlag = hitPlayer.PlayerIndex == 0;
            
            
            AudioManager.PlayCue("ball_hit_new");
        }

        public void Update(GameTime gameTime)
        {
            //move the ball
            
            position += direction * Speed * gameTime.ElapsedGameTime.Milliseconds / 1000.0f;
            model.World = Matrix.CreateTranslation(position);
            
            ////ball-debug-movement-control
            //if(Motoball.input.IsKeyPress(Microsoft.Xna.Framework.Input.Keys.I))
            //    position += new Vector3(0,0,10);
            //if(Motoball.input.IsKeyPress(Microsoft.Xna.Framework.Input.Keys.J))
            //    position += new Vector3(10,0,0);
            //if(Motoball.input.IsKeyPress(Microsoft.Xna.Framework.Input.Keys.K))
            //    position += new Vector3(-10,0,0);
            //if(Motoball.input.IsKeyPress(Microsoft.Xna.Framework.Input.Keys.M))
            //    position += new Vector3(0,0,-10);
        }

        public void Draw(GameTime gameTime)
        {
            GameScreen.screenManager.AddDebugString(bla.ToString());
            if (active && !model.blooming)
            {
                rotation += (float)gameTime.ElapsedGameTime.TotalMilliseconds/1000f;
                if (rotation > MathHelper.TwoPi)
                    rotation -= MathHelper.TwoPi;
                Matrix outerRing = Matrix.CreateRotationX(rotation);
                Matrix centerRing = outerRing * Matrix.CreateRotationY(rotation);
                Matrix innerRing = centerRing * Matrix.CreateRotationZ(rotation);

                rings[0].Transform = outerRing * ringMatrices[0];
                rings[1].Transform = centerRing * ringMatrices[1];
                rings[2].Transform = innerRing * ringMatrices[2];

                foreach (ModelMesh mesh in model.model.Meshes)
                {
                    foreach (BasicEffect be in mesh.Effects)
                    {
                        be.SpecularColor = model.diffColors[mesh.Name]*1.5f;
                    }
                }
            }
            
            model.Draw(Camera);
        }
        public Vector3 RotateY(Vector3 vector, float radians)
        {
            Vector3 temp = vector;
            temp.X = vector.X * (float)Math.Cos(radians) - vector.Z * (float)Math.Sin(radians);
            temp.Z = vector.X * (float)Math.Sin(radians) + vector.Z * (float)Math.Cos(radians);
            return temp;
        }
        #endregion
    }
}
